package org.lex.ftp;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.swing.ActionMap;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.lex.app.SharedApplicationContext;
import org.lex.explorer.Explorer;
import org.lex.ftp.net.MyFTPClientFactory;
import org.lex.ftp.queue.ITransferQueue;
import org.lex.ftp.ui.MainContentPane;
import org.lex.ftp.ui.MainMenuBar;
import org.lex.ftp.ui.SessionsTableModel;
import org.lex.ftp.ui.Splash;
import org.lex.ftp.ui.StatusBar;
import org.lex.ftp.ui.actions.AbortAction;
import org.lex.ftp.ui.actions.CalculateSizeAction;
import org.lex.ftp.ui.actions.ConnectAction;
import org.lex.ftp.ui.actions.DisconnectAction;
import org.lex.ftp.ui.actions.ExitAction;
import org.lex.ftp.ui.actions.FindAction;
import org.lex.ftp.ui.actions.NewInstanceAction;
import org.lex.ftp.ui.actions.PreferencesAction;
import org.lex.ftp.ui.actions.SessionsAction;
import org.lex.ftp.ui.actions.TransferAction;
import org.lex.ftp.ui.explorer.FTPExplorer;
import org.lex.ftp.util.Actions;
import org.lex.ftp.util.prefs.DefaultConfiguration;
import org.lex.ftp.util.prefs.Keys;
import org.lex.net.log.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FTP {
	private static FTP INSTANCE = null;
	public static final String APPID = "lexftp";
	private static final SharedApplicationContext context = new SharedApplicationContext(APPID);
	private static final boolean AUTO_CONNECT = false;
	// ==============================================
	private JFrame mainframe = null;
	private MainContentPane contentPane = null;
	private ActionMap actionMap = null;
	private final Logger log = LoggerFactory.getLogger(FTP.class);

	public static void main(String[] args) {
		Splash.setStatus("Starting Program ...");
		globalInitialize(args);
		INSTANCE = new FTP();
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				INSTANCE.getRootWindow().setVisible(true);
				INSTANCE.getGlobalLogger().misc(null, "Using " + MyFTPClientFactory.getInstance().newFTPClient().getClass().getName());
				if (AUTO_CONNECT) {
					INSTANCE.getGlobalLogger().misc(null, "Using " + MyFTPClientFactory.getInstance().newFTPClient().getClass().getName());
				}
			}
		});
	}

	public static FTP getApplication() {
		return INSTANCE;
	}

	public static SharedApplicationContext getContext() {
		return context;
	}

	public FTP() {
		this.initializeActionMap();
		getContext().getSessionStorage().restore(this.getRootWindow());
		this.getRootWindow().setVisible(true);
		SessionsTableModel.getInstance().add(this);
	}

	/***************************************************************************
	 * Delegate Methods
	 **************************************************************************/
	public Log getGlobalLogger() {
		return getContentPane().getGlobalLogger();
	}

	public FTPExplorer getFTPExplorer() {
		return this.getContentPane().getFTPExplorer();
	}

	public Explorer getFileExplorer() {
		return getContentPane().getFileExplorer();
	}

	public StatusBar getStatusPane() {
		return getContentPane().getStatusPane();
	}

	public ITransferQueue getQueue() {
		return this.getContentPane().getQueuePane().getQueue();
	}

	public boolean isConnected() {
		return this.getFTPExplorer().isConnected();
	}

	public JFrame getRootWindow() {
		if (null == mainframe) {
			mainframe = new JFrame("FTP");
			mainframe.setName(getClass().getName() + ".mainframe");
			mainframe.setJMenuBar(new MainMenuBar(this));
			mainframe.setContentPane(this.getContentPane());
			mainframe.addWindowListener(new WindowAdapter() {
				@Override
				public void windowClosing(WindowEvent e) {
					exit();
				}
			});
		}
		return mainframe;
	}

	public MainContentPane getContentPane() {
		if (null == contentPane) {
			Splash.setStatus("Initializing Main Frame ...");
			this.contentPane = new MainContentPane(this);
		}
		return this.contentPane;
	}

	public ActionMap getActionMap() {
		if (null == actionMap)
			actionMap = new ActionMap();
		return actionMap;
	}

	private void initializeActionMap() {
		ActionMap am = this.getActionMap();
		am.put(Actions.ABORT, new AbortAction(this));
		am.put(Actions.CALCULATE_SIZE, new CalculateSizeAction(this));
		am.put(Actions.CONNECT, new ConnectAction(this));
		am.put(Actions.DISCONNECT, new DisconnectAction(this));
		am.put(Actions.EXIT, new ExitAction(this));
		am.put(Actions.FIND, new FindAction(this));
		am.put(Actions.NEW_SESSION, new NewInstanceAction(this));
		am.put(Actions.PREFERENCES, new PreferencesAction(this));
		am.put(Actions.SESSIONS, new SessionsAction(this));
		am.put(Actions.TRANSFER, new TransferAction(this));
	}

	public void exit() {
		this.getFTPExplorer().close();
		this.saveResources();
		this.getRootWindow().dispose();
		SessionsTableModel.getInstance().remove(this);
	}

	private void saveResources() {
		SharedApplicationContext context = getContext();
		context.getSessionStorage().save(mainframe);
		context.getResourceMap().putString(Keys.DOWNLOAD_PATH, this.getFileExplorer().getDirectory().getAbsolutePath());
		try {
			context.getResourceManager().save();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void globalInitialize(String[] args) {
		System.out.println("args: " + java.util.Arrays.toString(args));
		setupLookAndFeel();
		try {
			context.getResourceManager().load();
		} catch (IOException e) {
			e.printStackTrace();
		}
		DefaultConfiguration.loadDefaultConfiguration(getContext().getResourceMap());
	}

	private static void setupLookAndFeel() {
		UIManager.put("swing.boldMetal", false);
	}
}
